package com.zeei.bfs.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zeei.bfs.dao.ButtonMenuDao;
import com.zeei.bfs.dao.MenuDao;
import com.zeei.bfs.dao.RoleMenuDao;
import com.zeei.bfs.dao.UserMenuDao;
import com.zeei.bfs.service.MenuService;
import com.zeei.bfs.vo.QueryMenuParamVO;
import com.zeei.bfs.vo.RoleMenuVO;
import com.zeei.bfs.vo.UserMenuVO;
import com.zeei.common.constant.GlobalConstant;
import com.zeei.common.utils.SessionInfoUtil;
import com.zeei.common.utils.StringUtil;
import com.zeei.common.utils.TreeUtil;
import com.zeei.common.vo.ButtonMenuVO;
import com.zeei.common.vo.MenuVO;
import com.zeei.common.vo.PointSysTypeVO;
import com.zeei.common.vo.TreeNodeVO;
import com.zeei.common.vo.UserVO;

@Service("menuService")
public class MenuServiceImpl extends BasicServiceImpl implements MenuService {

	@Autowired
	private MenuDao menuDao;

	@Autowired
	private RoleMenuDao roleMenuDao;

	@Autowired
	private UserMenuDao userMenuDao;

	@Autowired
	private ButtonMenuDao buttonMenuDao;

	@Override
	public List<TreeNodeVO<MenuVO>> queryRoleMenu(Integer roleId, String systemType) {
		if (roleId == null) {
			return new ArrayList<TreeNodeVO<MenuVO>>();
		}
		// 登陆用户的权限的基础上设置用户的权限
		// 1)查询当前用户关联的菜单权限
		/*
		 * List<MenuVO> currentMenuList =
		 * menuDao.queryUserMenu(SessionInfoUtil.getSessionUserId());
		 * List<String> menuIdList = new ArrayList<String>(); for (MenuVO menu :
		 * currentMenuList) { String menuId = menu.getId();
		 * menuIdList.add(menuId); }
		 */
		// 2)根据登陆用户的菜单权限查询角色关联的菜单
		Map<String, Object> condition = new HashMap<String, Object>();
		condition.put("roleId", roleId);
		condition.put("menuCode", systemType.toString());
		// condition.put("menuIdList", menuIdList);
		condition.put("userId", SessionInfoUtil.getSessionUserId());
		List<MenuVO> menuList = menuDao.queryRoleMenu(condition);
		if (CollectionUtils.isNotEmpty(menuList)) {
			// 查询当前用户关联的按钮权限
			Map<String, Object> buttonCondition = new HashMap<String, Object>();
			buttonCondition.put("userId", SessionInfoUtil.getSessionUserId());
			buttonCondition.put("roleId", roleId);
			List<ButtonMenuVO> buttonMenuList = buttonMenuDao.queryRoleButtonMenuByCondition(buttonCondition);
			addMenuButton(menuList, buttonMenuList);
			List<TreeNodeVO<MenuVO>> menutree = TreeUtil.buildTreeNodeTree(menuList, null);
			List<TreeNodeVO<MenuVO>> emptyList = new ArrayList<TreeNodeVO<MenuVO>>();
			for (TreeNodeVO<MenuVO> vo : menutree) {
				if (StringUtil.isEmpty(vo.getParentId()) && (vo.getChildren() == null || vo.getChildren().isEmpty())) {
					emptyList.add(vo);
				}
			}
			if (emptyList != null && !emptyList.isEmpty()) {
				menutree.removeAll(emptyList);
			}
			return menutree;
		}
		return new ArrayList<TreeNodeVO<MenuVO>>();
	}

	/**
	 * 方法描述:添加菜单的按钮
	 *
	 * @param menuList
	 * @param buttonMenuList
	 */
	private void addMenuButton(List<MenuVO> menuList, List<ButtonMenuVO> buttonMenuList) {
		Map<Integer, List<ButtonMenuVO>> buttonMenuMap = buttonListConvertMap(buttonMenuList);
		setMenuButtonList(menuList, buttonMenuMap);
	}

	/**
	 * 方法描述:将List装换成Map,键为菜单ID,值为菜单ID对应的按钮List
	 *
	 * @param buttonMenuList
	 * @return
	 */
	private Map<Integer, List<ButtonMenuVO>> buttonListConvertMap(List<ButtonMenuVO> buttonMenuList) {
		Map<Integer, List<ButtonMenuVO>> buttonMenuMap = new HashMap<Integer, List<ButtonMenuVO>>();
		for (int i = 0; i < buttonMenuList.size(); i++) {
			ButtonMenuVO buttonMenu = buttonMenuList.get(i);
			Integer menuId = buttonMenu.getMenuId();
			List<ButtonMenuVO> buttonList = buttonMenuMap.get(menuId);
			if (buttonList != null) {
				buttonList.add(buttonMenu);
			} else {
				buttonList = new ArrayList<ButtonMenuVO>();
				buttonList.add(buttonMenu);
				buttonMenuMap.put(menuId, buttonList);
			}
		}
		return buttonMenuMap;
	}

	/**
	 * 方法描述:对菜单设置按钮关系
	 *
	 * @param menuList
	 * @param buttonMenuMap
	 */
	private void setMenuButtonList(List<MenuVO> menuList, Map<Integer, List<ButtonMenuVO>> buttonMenuMap) {
		for (int i = 0; i < menuList.size(); i++) {
			MenuVO menu = menuList.get(i);
			if (!StringUtil.isEmpty(menu.getParentId())) {
				Integer menuId = menu.getMenuId();
				menu.setButtonList(buttonMenuMap.get(menuId));
			}
		}
	}

	@Override
	public boolean addRoleMenu(Integer createId, Integer roleId, List<MenuVO> menuList) {
		if (roleId == null) {
			return GlobalConstant.FAILED;
		}
		if (CollectionUtils.isEmpty(menuList)) {
			roleMenuDao.deleteRoleMenuByRoleId(roleId);
			return GlobalConstant.SUCCEED;
		}
		roleMenuDao.deleteRoleMenuByRoleId(roleId);
		List<RoleMenuVO> roleMenuList = menuListConvertRoleMenuList(menuList, roleId, createId);
		if (CollectionUtils.isNotEmpty(roleMenuList)) {
			int N = GlobalConstant.DEFAULT_BATCH_SIZE;
			int size = roleMenuList.size();
			int index = 0;
			int toIndex = N;
			while (toIndex < size) {
				roleMenuDao.insertRoleMenuList(roleMenuList.subList(index, toIndex));
				toIndex += N;
				index += N;
			}
			roleMenuDao.insertRoleMenuList(roleMenuList.subList(index, size));
		}
		return GlobalConstant.SUCCEED;
	}

	private List<RoleMenuVO> menuListConvertRoleMenuList(List<MenuVO> menuList, Integer roleId, Integer createId) {
		List<RoleMenuVO> roleMenuList = new ArrayList<RoleMenuVO>();
		for (int i = 0; i < menuList.size(); i++) {// 菜单
			MenuVO menu = menuList.get(i);
			RoleMenuVO roleMenu = new RoleMenuVO();
			roleMenu.setRoleId(roleId);
			roleMenu.setMenuId(menu.getMenuId());
			roleMenu.setCreateId(createId);
			roleMenu.setType(1);
			roleMenu.setButtonId(-1);
			roleMenuList.add(roleMenu);
			List<ButtonMenuVO> buttonList = menu.getButtonList();
			if (CollectionUtils.isNotEmpty(buttonList)) {// 菜单按钮
				for (int j = 0; j < buttonList.size(); j++) {
					Integer buttonId = buttonList.get(j).getButtonId();
					RoleMenuVO roleButton = new RoleMenuVO();
					roleButton.setRoleId(roleId);
					roleButton.setMenuId(menu.getMenuId());
					roleButton.setButtonId(buttonId);
					roleButton.setCreateId(createId);
					roleButton.setType(2);
					roleMenuList.add(roleButton);
				}
			}
		}
		return roleMenuList;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public List<TreeNodeVO<MenuVO>> queryUserMenu(Integer userId) {

		List<TreeNodeVO<MenuVO>> lsData = new ArrayList<TreeNodeVO<MenuVO>>();

		Map condition = new HashMap();
		condition.put("userId", userId);

		List<MenuVO> menuList = menuDao.queryUserMenuForestByCondition(condition);
		if (CollectionUtils.isNotEmpty(menuList)) {
			lsData = TreeUtil.buildTree(menuList, null);
		}

		return lsData;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public boolean addUserMenu(Integer createId, Integer userId, Integer[] menuIds) {
		if (userId == null) {
			return GlobalConstant.FAILED;
		}
		if (menuIds == null) {
			userMenuDao.deleteUserMenuByUserId(userId);
			return GlobalConstant.SUCCEED;
		}
		// 1)查询
		Map condition = new HashMap();
		condition.put("userId", userId);
		List<UserMenuVO> userMenuList = userMenuDao.queryUserMenuByCondition(condition);
		// 2)匹配
		Map<Integer, UserMenuVO> userMenuMap = new HashMap<Integer, UserMenuVO>(userMenuList.size());
		for (UserMenuVO vo : userMenuList) {
			userMenuMap.put(vo.getMenuId(), vo);
		}

		List<UserMenuVO> deleteList = new ArrayList<UserMenuVO>();
		List<UserMenuVO> insertList = new ArrayList<UserMenuVO>();

		Map<Integer, Integer> menuMap = new HashMap<Integer, Integer>(menuIds.length);
		for (Integer menuId : menuIds) {
			UserMenuVO userMenuVO = userMenuMap.get(menuId);
			if (userMenuVO == null) {// 找不到增加
				UserMenuVO vo = new UserMenuVO();
				vo.setUserId(userId);
				vo.setMenuId(menuId);
				vo.setCreateId(createId);
				insertList.add(vo);
			}
			menuMap.put(menuId, menuId);
		}
		for (Entry<Integer, UserMenuVO> entry : userMenuMap.entrySet()) {// 如果查找的数据在传递的数据中没找到,删除
			Integer menuId = entry.getKey();
			UserMenuVO userMenuVO = entry.getValue();
			if (menuMap.get(menuId) == null) {
				deleteList.add(userMenuVO);
			}
		}
		// 3)delete or insert
		for (UserMenuVO vo : deleteList) {
			userMenuDao.deleteUserMenu(vo);
		}
		if (CollectionUtils.isNotEmpty(insertList)) {
			int N = GlobalConstant.DEFAULT_BATCH_SIZE;
			for (int i = 0; i < insertList.size(); i += N) {
				int toIndex = (insertList.size() > (i + N) ? i + N : insertList.size());
				userMenuDao.insertUserMenuList(insertList.subList(i, toIndex));
			}
		}
		return GlobalConstant.SUCCEED;
	}

	@Override
	public Map<String, MenuVO> queryUserMenuMap(Integer userId) {
		if (userId == null) {
			return new HashMap<String, MenuVO>();
		}
		// 1)根据用户查找用户有关联的菜单
		List<MenuVO> menuList = menuDao.queryUserMenu(userId);
		Map<String, MenuVO> menuUriMap = new HashMap<String, MenuVO>(menuList.size());
		for (MenuVO vo : menuList) {
			if (vo.getUserId() != null && StringUtils.isNotEmpty(vo.getMenuUrl())) {
				menuUriMap.put(vo.getMenuUrl(), vo);
			}
		}
		return menuUriMap;
	}

	@Override
	public List<MenuVO> queryUserFirstMenu(UserVO userInfo) {
		List<MenuVO> menuList = menuDao.queryUserFirstMenu(userInfo.getUserid());
		return menuList;
	}

	@Override
	public List<TreeNodeVO<MenuVO>> queryUserChildMenu(Integer userId, Integer menuId, String systemType) {
		Map<String, Object> condition = new HashMap<String, Object>();
		condition.put("userId", userId);
		condition.put("menuCode", systemType);
		condition.put("sType", "0");
		List<MenuVO> menuList = menuDao.queryUserMenuByCondition(condition);
		List<TreeNodeVO<MenuVO>> rootList = TreeUtil.buildTree(menuList, this.toString(menuId));
		return rootList;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public boolean addUserMenu(List<MenuVO> menuList, Integer userId) {
		// 1)查询
		Map condition = new HashMap();
		condition.put("userId", userId);
		List<UserMenuVO> userMenuList = userMenuDao.queryUserMenuByCondition(condition);
		// 2)匹配
		// Map<Integer, MenuVO> menuMap = new HashMap<Integer,
		// MenuVO>(menuList.size());
		// menuTreeListToMap(menuList, menuMap);

		Map<Integer, UserMenuVO> userMenuMap = new HashMap<Integer, UserMenuVO>(userMenuList.size());
		for (UserMenuVO vo : userMenuList) {
			userMenuMap.put(vo.getMenuId(), vo);
		}

		List<UserMenuVO> updateList = new ArrayList<UserMenuVO>();
		List<UserMenuVO> insertList = new ArrayList<UserMenuVO>();

		for (MenuVO entry : menuList) {
			Integer menuId = entry.getMenuId();
			MenuVO menuVO = entry;
			UserMenuVO userMenuVO = userMenuMap.get(menuId);
			if (userMenuVO == null) {// 找不到增加
				UserMenuVO vo = new UserMenuVO();
				vo.setUserId(userId);
				vo.setMenuId(menuId);
				vo.setOrderNum(menuVO.getOrderNum());
				vo.setCreateId(userId);
				insertList.add(vo);
			} else if (menuVO.getOrderNum() != null && !menuVO.getOrderNum().equals(userMenuVO.getOrderNum())) {// 修改了排序进行修改
				userMenuVO.setOrderNum(menuVO.getOrderNum());
				updateList.add(userMenuVO);
			}
		}
		// 3)update or insert
		for (UserMenuVO vo : updateList) {
			userMenuDao.updateOrderNum(vo);
		}
		if (CollectionUtils.isNotEmpty(insertList)) {
			int N = GlobalConstant.DEFAULT_BATCH_SIZE;
			for (int i = 0; i < insertList.size(); i += N) {
				int toIndex = (insertList.size() > (i + N) ? i + N : insertList.size());
				userMenuDao.insertUserMenuAllParamList(insertList.subList(i, toIndex));
			}
		}
		return GlobalConstant.SUCCEED;
	}

	@Override
	public List<TreeNodeVO<MenuVO>> queryMenu(QueryMenuParamVO queryMenuParam) {
		String searchMenuName = StringUtil.trim(queryMenuParam.getSearchMenuName());
		String searchMenuState = queryMenuParam.getSearchMenuState();

		Map<String, Object> condition = new HashMap<String, Object>();
		condition.put("searchMenuName", searchMenuName);
		condition.put("searchMenuState", searchMenuState);
		condition.put("userId", SessionInfoUtil.getSessionUserId());
		List<MenuVO> menuList = menuDao.queryMenuByCondition(condition);

		List<TreeNodeVO<MenuVO>> menuTree = new ArrayList<TreeNodeVO<MenuVO>>();
		// 启用：没有禁用的和没有禁用下的所有节点的树.
		// 禁用：禁用的节点和其父到根的节点的树.
		if (StringUtils.isNotBlank(searchMenuName) || StringUtils.isNotBlank(searchMenuState)) {// 进行搜索处理
			List<MenuVO> allList = menuDao.queryMenuByCondition(new HashMap<String, Object>());
			List<TreeNodeVO<MenuVO>> treeList = TreeUtil.buildSearchNodeTree(allList, menuList);
			// 进行搜索的相关设置
			// menuTree=TreeUtil.buildSearchTreeNodeTree(menuList, treeList);
			menuTree = treeList;
		} else {
			menuTree = TreeUtil.buildTreeNodeTree(menuList, null);
			TreeUtil.setInitCloseState(menuTree);
		}
		List<TreeNodeVO<MenuVO>> emptyList = new ArrayList<TreeNodeVO<MenuVO>>();
		for (TreeNodeVO<MenuVO> vo : menuTree) {
			if (StringUtil.isEmpty(vo.getParentId()) && (vo.getChildren() == null || vo.getChildren().isEmpty())) {
				emptyList.add(vo);
			}
		}
		if (emptyList != null && !emptyList.isEmpty()) {
			menuTree.removeAll(emptyList);
		}

		return menuTree;
	}

	@Override
	public boolean addMenu(MenuVO menu, UserVO user) {
		if (menu.getPid().toString().equals(menu.getMenuCode())) {
			menu.setPid(null);
		}
		Integer count = menuDao.insertMenu(menu);
		UserMenuVO userMenu = new UserMenuVO();
		userMenu.setUserId(user.getUserid());
		userMenu.setMenuId(menu.getMenuId());
		userMenu.setCreateId(user.getUserid());
		userMenuDao.insertUserMenu(userMenu);
		return count > 0;
	}

	@Override
	public boolean dropMenu(List<Integer> menuIds) {
		// // 1)删除用户与菜单的关联关系
		// userMenuDao.deleteUserMenuByMenuIds(menuIds);
		// // 2)删除角色与菜单的关联关系
		// roleMenuDao.deleteRoleMenuByMenuIds(menuIds);
		// // 3)删除按钮与菜单的关联关系
		// buttonMenuDao.deleteButtonMenuByMenuIds(menuIds);
		// // 4)删除菜单
		// Integer count = menuDao.deleteMenuByIds(menuIds);
		Integer count = menuDao.removeMenuByIds(menuIds);
		return count > 0;
	}

	@Override
	public boolean validMenuName(MenuVO menu) {
		if (isNotValid(menu)) {
			return false;
		}
		// 假定全部的menuCode是''
		if (isUpdateNotChangeNameCode(menu.getMenuId(), menu.getMenuCode(), menu.getMenuName())) {
			return true;
		}
		if (isNotExistNameCode(menu.getMenuName(), menu.getMenuCode())) {
			return true;
		}
		return false;
	}

	private boolean isNotExistNameCode(String menuName, String menuCode) {
		MenuVO queryVO = new MenuVO();
		queryVO.setMenuName(menuName);
		queryVO.setMenuCode(menuCode);
		List<MenuVO> menuList = menuDao.queryMenu(queryVO);
		if (CollectionUtils.isNotEmpty(menuList)) {
			return false;// 失败
		}
		return true;
	}

	private boolean isUpdateNotChangeNameCode(Integer menuId, String menuCode, String menuName) {
		if (menuId == null) {
			return false;
		}
		MenuVO queryVO = new MenuVO();
		queryVO.setMenuId(menuId);
		queryVO.setMenuCode(menuCode);
		List<MenuVO> oldList = menuDao.queryMenu(queryVO);
		if (CollectionUtils.isNotEmpty(oldList) && menuName.equals(oldList.get(0).getMenuName()) && menuCode != null
				&& menuCode.equals(oldList.get(0).getMenuCode())) {// 系统编码和系统名称都没有改变则不用验证
			return true;
		}
		return false;
	}

	private static boolean isNotValid(MenuVO menu) {
		return menu == null || StringUtils.isEmpty(menu.getMenuName());
	}

	@Override
	public boolean editMenu(MenuVO menu) {
		if (menu == null || menu.getMenuId() == null) {
			return GlobalConstant.FAILED;
		}
		if (menu.getPid().toString().equals(menu.getMenuCode())) {
			menu.setPid(null);
		}
		// 修改当前菜单数据
		Integer count = menuDao.updateMenuById(menu);
		return count > 0;
	}

	@Override
	public List<TreeNodeVO<MenuVO>> queryMenu() {
		List<MenuVO> menuTree = menuDao.queryMenuByCondition(new HashMap<String, Object>());
		List<TreeNodeVO<MenuVO>> menuTreeList = TreeUtil.buildTreeNodeTree(menuTree, null);
		List<TreeNodeVO<MenuVO>> emptyList = new ArrayList<TreeNodeVO<MenuVO>>();
		for (TreeNodeVO<MenuVO> vo : menuTreeList) {
			vo.setState(TreeNodeVO.CLOSED_STATE);
			if (StringUtil.isEmpty(vo.getParentId()) && (vo.getChildren() == null || vo.getChildren().isEmpty())) {
				emptyList.add(vo);
			}
		}
		if (emptyList != null && !emptyList.isEmpty()) {
			menuTreeList.removeAll(emptyList);
		}

		return menuTreeList;
	}

	/**
	 * 获取系统类型
	 */
	@Override
	public List<PointSysTypeVO> getSystemTable() {
		return menuDao.getSystemTable();
	}

}
